Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
matrix.c File Reference
+ Include dependency graph for matrix.c:

Go to the source code of this file.

Macros

#define CORRUPTMATRIX   0.001F
 
#define NITERATIONS   15
 
#define NITERATIONS   15
 

Functions

void f3x3matrixAeqI (float A[][3])
 
void f3x3matrixAeqB (float A[][3], float B[][3])
 
void fmatrixAeqI (float *A[], int16 rc)
 
void f3x3matrixAeqScalar (float A[][3], float Scalar)
 
void f3x3matrixAeqAxScalar (float A[][3], float Scalar)
 
void f3x3matrixAeqMinusA (float A[][3])
 
void f3x3matrixAeqInvSymB (float A[][3], float B[][3])
 
float f3x3matrixDetA (float A[][3])
 
void fEigenCompute10 (float A[][10], float eigval[], float eigvec[][10], int8 n)
 
void fEigenCompute4 (float A[][4], float eigval[], float eigvec[][4], int8 n)
 
void fComputeEigSlice (float fmatA[10][10], float fmatB[10][10], float fvecA[10], int8 i, int8 j, int8 iMatrixSize)
 
void fmatrixAeqInvA (float *A[], int8 iColInd[], int8 iRowInd[], int8 iPivot[], int8 isize, int8 *pierror)
 
void fveqRu (float fv[], float fR[][3], float fu[], int8 itranspose)
 
void fVeq3x3AxV (float V[3], float A[][3])
 

Detailed Description

Contains functions for basic manipulation of 3x3 matrices

Definition in file matrix.c.

Macro Definition Documentation

#define CORRUPTMATRIX   0.001F

Definition at line 42 of file matrix.c.

#define NITERATIONS   15

Referenced by fEigenCompute10(), and fEigenCompute4().

#define NITERATIONS   15

Function Documentation

void f3x3matrixAeqAxScalar ( float  A[][3],
float  Scalar 
)

function multiplies all elements of 3x3 matrix A by the specified scalar

Definition at line 128 of file matrix.c.

Referenced by fComputeMagCalibration10(), fComputeMagCalibration7(), and fUpdateMagCalibration10Slice().

129 {
130  float *pAij; // pointer to A[i][j]
131  int8 i,
132  j; // loop counters
133  for (i = 0; i < 3; i++)
134  {
135  // set pAij to &A[i][j=0]
136  pAij = A[i];
137  for (j = 0; j < 3; j++)
138  {
139  *(pAij++) *= Scalar;
140  }
141  }
142 
143  return;
144 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void f3x3matrixAeqB ( float  A[][3],
float  B[][3] 
)

function sets 3x3 matrix A to 3x3 matrix B

Definition at line 66 of file matrix.c.

Referenced by fRun_6DOF_GY_KALMAN().

67 {
68  float *pAij; // pointer to A[i][j]
69  float *pBij; // pointer to B[i][j]
70  int8 i,
71  j; // loop counters
72  for (i = 0; i < 3; i++)
73  {
74  // set pAij to &A[i][j=0] and pBij to &B[i][j=0]
75  pAij = A[i];
76  pBij = B[i];
77  for (j = 0; j < 3; j++)
78  {
79  *(pAij++) = *(pBij++);
80  }
81  }
82 
83  return;
84 }
#define B
Definition: status.c:50
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void f3x3matrixAeqI ( float  A[][3])

function sets the 3x3 matrix A to the identity matrix

Definition at line 45 of file matrix.c.

Referenced by f3DOFMagnetometerMatrixAndroid(), f3DOFMagnetometerMatrixNED(), f3x3matrixAeqInvSymB(), fComputeMagCalibration4(), fComputeMagCalibration7(), feCompassAndroid(), feCompassNED(), feCompassWin8(), fInit_3DOF_Y_BASIC(), fInitializeAccelCalibration(), fInitializeMagCalibration(), and fUpdateMagCalibration4Slice().

46 {
47  float *pAij; // pointer to A[i][j]
48  int8 i,
49  j; // loop counters
50  for (i = 0; i < 3; i++)
51  {
52  // set pAij to &A[i][j=0]
53  pAij = A[i];
54  for (j = 0; j < 3; j++)
55  {
56  *(pAij++) = 0.0F;
57  }
58 
59  A[i][i] = 1.0F;
60  }
61 
62  return;
63 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void f3x3matrixAeqInvSymB ( float  A[][3],
float  B[][3] 
)

function directly calculates the symmetric inverse of a symmetric 3x3 matrix only the on and above diagonal terms in B are used and need to be specified

Definition at line 168 of file matrix.c.

Referenced by fComputeAccelCalibration10(), fComputeMagCalibration10(), and fUpdateMagCalibration10Slice().

169 {
170  float fB11B22mB12B12; // B[1][1] * B[2][2] - B[1][2] * B[1][2]
171  float fB12B02mB01B22; // B[1][2] * B[0][2] - B[0][1] * B[2][2]
172  float fB01B12mB11B02; // B[0][1] * B[1][2] - B[1][1] * B[0][2]
173  float ftmp; // determinant and then reciprocal
174 
175  // calculate useful products
176  fB11B22mB12B12 = B[1][1] * B[2][2] - B[1][2] * B[1][2];
177  fB12B02mB01B22 = B[1][2] * B[0][2] - B[0][1] * B[2][2];
178  fB01B12mB11B02 = B[0][1] * B[1][2] - B[1][1] * B[0][2];
179 
180  // set ftmp to the determinant of the input matrix B
181  ftmp = B[0][0] *
182  fB11B22mB12B12 +
183  B[0][1] *
184  fB12B02mB01B22 +
185  B[0][2] *
186  fB01B12mB11B02;
187 
188  // set A to the inverse of B for any determinant except zero
189  if (ftmp != 0.0F)
190  {
191  ftmp = 1.0F / ftmp;
192  A[0][0] = fB11B22mB12B12 * ftmp;
193  A[1][0] = A[0][1] = fB12B02mB01B22 * ftmp;
194  A[2][0] = A[0][2] = fB01B12mB11B02 * ftmp;
195  A[1][1] = (B[0][0] * B[2][2] - B[0][2] * B[0][2]) * ftmp;
196  A[2][1] = A[1][2] = (B[0][2] * B[0][1] - B[0][0] * B[1][2]) * ftmp;
197  A[2][2] = (B[0][0] * B[1][1] - B[0][1] * B[0][1]) * ftmp;
198  }
199  else
200  {
201  // provide the identity matrix if the determinant is zero
202  f3x3matrixAeqI(A);
203  }
204 
205  return;
206 }
#define B
Definition: status.c:50
void f3x3matrixAeqI(float A[][3])
function sets the 3x3 matrix A to the identity matrix
Definition: matrix.c:45

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void f3x3matrixAeqMinusA ( float  A[][3])

function negates all elements of 3x3 matrix A

Definition at line 147 of file matrix.c.

Referenced by fComputeAccelCalibration10(), fComputeMagCalibration10(), fComputeMagCalibration7(), and fUpdateMagCalibration10Slice().

148 {
149  float *pAij; // pointer to A[i][j]
150  int8 i,
151  j; // loop counters
152  for (i = 0; i < 3; i++)
153  {
154  // set pAij to &A[i][j=0]
155  pAij = A[i];
156  for (j = 0; j < 3; j++)
157  {
158  *pAij = -*pAij;
159  pAij++;
160  }
161  }
162 
163  return;
164 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void f3x3matrixAeqScalar ( float  A[][3],
float  Scalar 
)

function sets every entry in the 3x3 matrix A to a constant scalar

Definition at line 109 of file matrix.c.

Referenced by fComputeAccelCalibration7(), and fComputeMagCalibration7().

110 {
111  float *pAij; // pointer to A[i][j]
112  int8 i,
113  j; // counters
114  for (i = 0; i < 3; i++)
115  {
116  // set pAij to &A[i][j=0]
117  pAij = A[i];
118  for (j = 0; j < 3; j++)
119  {
120  *(pAij++) = Scalar;
121  }
122  }
123 
124  return;
125 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

float f3x3matrixDetA ( float  A[][3])

function calculates the determinant of a 3x3 matrix

Definition at line 209 of file matrix.c.

Referenced by fComputeAccelCalibration10(), fComputeMagCalibration10(), and fUpdateMagCalibration10Slice().

210 {
211  return
212  (
213  A[CHX][CHX] *
214  (
215  A[CHY][CHY] *
216  A[CHZ][CHZ] -
217  A[CHY][CHZ] *
218  A[CHZ][CHY]
219  ) +
220  A[CHX][CHY] *
221  (A[CHY][CHZ] * A[CHZ][CHX] - A[CHY][CHX] * A[CHZ][CHZ]) +
222  A[CHX][CHZ] *
223  (A[CHY][CHX] * A[CHZ][CHY] - A[CHY][CHY] * A[CHZ][CHX])
224  );
225 }
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
#define CHZ
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76

+ Here is the caller graph for this function:

void fComputeEigSlice ( float  fmatA[10][10],
float  fmatB[10][10],
float  fvecA[10],
int8  i,
int8  j,
int8  iMatrixSize 
)

Definition at line 572 of file matrix.c.

Referenced by fUpdateMagCalibration10Slice(), and fUpdateMagCalibration7Slice().

574 {
575  float cot2phi; // cotangent of half jacobi rotation angle
576  float tanhalfphi; // tangent of half jacobi rotation angle
577  float tanphi; // tangent of jacobi rotation angle
578  float sinphi; // sine of jacobi rotation angle
579  float cosphi; // cosine of jacobi rotation angle
580  float ftmp; // scratch
581  int8 k; // loop counter
582 
583  // calculate cot(2*phi) where phi is the Jacobi rotation angle
584  cot2phi = 0.5F * (fvecA[j] - fvecA[i]) / (fmatA[i][j]);
585 
586  // calculate tan(phi) correcting sign to ensure the smaller solution is used
587  tanphi = 1.0F / (fabsf(cot2phi) + sqrtf(1.0F + cot2phi * cot2phi));
588  if (cot2phi < 0.0F) tanphi = -tanphi;
589 
590  // calculate the sine and cosine of the Jacobi rotation angle phi
591  cosphi = 1.0F / sqrtf(1.0F + tanphi * tanphi);
592  sinphi = tanphi * cosphi;
593 
594  // calculate tan(phi/2)
595  tanhalfphi = sinphi / (1.0F + cosphi);
596 
597  // set tmp = tan(phi) times current matrix element used in update of leading diagonal elements
598  ftmp = tanphi * fmatA[i][j];
599 
600  // apply the jacobi rotation to diagonal elements [i][i] and [j][j] stored in the eigenvalue array
601  // fvecA[i] = fvecA[i] - tan(phi) * fmatA[i][j]
602  fvecA[i] -= ftmp;
603 
604  // fvecA[j] = fvecA[j] + tan(phi) * fmatA[i][j]
605  fvecA[j] += ftmp;
606 
607  // by definition, applying the jacobi rotation on element i, j results in 0.0
608  fmatA[i][j] = 0.0F;
609 
610  // apply the jacobi rotation to all elements of the eigenvector matrix
611  for (k = 0; k < iMatrixSize; k++)
612  {
613  // store fmatB[k][i]
614  ftmp = fmatB[k][i];
615 
616  // fmatB[k][i] = fmatB[k][i] - sin(phi) * (fmatB[k][j] + tan(phi/2) * fmatB[k][i])
617  fmatB[k][i] = ftmp - sinphi * (fmatB[k][j] + tanhalfphi * ftmp);
618 
619  // fmatB[k][j] = fmatB[k][j] + sin(phi) * (fmatB[k][i] - tan(phi/2) * fmatB[k][j])
620  fmatB[k][j] = fmatB[k][j] + sinphi * (ftmp - tanhalfphi * fmatB[k][j]);
621  }
622 
623  // apply the jacobi rotation only to those elements of matrix that can change
624  for (k = 0; k <= i - 1; k++)
625  {
626  // store fmatA[k][i]
627  ftmp = fmatA[k][i];
628 
629  // fmatA[k][i] = fmatA[k][i] - sin(phi) * (fmatA[k][j] + tan(phi/2) * fmatA[k][i])
630  fmatA[k][i] = ftmp - sinphi * (fmatA[k][j] + tanhalfphi * ftmp);
631 
632  // fmatA[k][j] = fmatA[k][j] + sin(phi) * (fmatA[k][i] - tan(phi/2) * fmatA[k][j])
633  fmatA[k][j] = fmatA[k][j] + sinphi * (ftmp - tanhalfphi * fmatA[k][j]);
634  }
635 
636  for (k = i + 1; k <= j - 1; k++)
637  {
638  // store fmatA[i][k]
639  ftmp = fmatA[i][k];
640 
641  // fmatA[i][k] = fmatA[i][k] - sin(phi) * (fmatA[k][j] + tan(phi/2) * fmatA[i][k])
642  fmatA[i][k] = ftmp - sinphi * (fmatA[k][j] + tanhalfphi * ftmp);
643 
644  // fmatA[k][j] = fmatA[k][j] + sin(phi) * (fmatA[i][k] - tan(phi/2) * fmatA[k][j])
645  fmatA[k][j] = fmatA[k][j] + sinphi * (ftmp - tanhalfphi * fmatA[k][j]);
646  }
647 
648  for (k = j + 1; k < iMatrixSize; k++)
649  {
650  // store fmatA[i][k]
651  ftmp = fmatA[i][k];
652 
653  // fmatA[i][k] = fmatA[i][k] - sin(phi) * (fmatA[j][k] + tan(phi/2) * fmatA[i][k])
654  fmatA[i][k] = ftmp - sinphi * (fmatA[j][k] + tanhalfphi * ftmp);
655 
656  // fmatA[j][k] = fmatA[j][k] + sin(phi) * (fmatA[i][k] - tan(phi/2) * fmatA[j][k])
657  fmatA[j][k] = fmatA[j][k] + sinphi * (ftmp - tanhalfphi * fmatA[j][k]);
658  }
659 
660  return;
661 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void fEigenCompute10 ( float  A[][10],
float  eigval[],
float  eigvec[][10],
int8  n 
)

function computes all eigenvalues and eigenvectors of a real symmetric matrix A[0..n-1][0..n-1] stored in the top left of a 10x10 array A[10][10]

Parameters
Areal symmetric matrix A[0..n-1][0..n-1]
eigvaleigval[0..n-1] returns the eigenvalues of A[][].
eigveceigvec[0..n-1][0..n-1] returns the normalized eigenvectors of A[][]
nn can vary up to and including 10 but the matrices A and eigvec must have 10 columns.

Definition at line 234 of file matrix.c.

Referenced by fComputeAccelCalibration10(), fComputeAccelCalibration7(), fComputeMagCalibration10(), and fComputeMagCalibration7().

235 {
236  // maximum number of iterations to achieve convergence: in practice 6 is typical
237 #define NITERATIONS 15
238  // various trig functions of the jacobi rotation angle phi
239  float cot2phi,
240  tanhalfphi,
241  tanphi,
242  sinphi,
243  cosphi;
244 
245  // scratch variable to prevent over-writing during rotations
246  float ftmp;
247 
248  // residue from remaining non-zero above diagonal terms
249  float residue;
250 
251  // matrix row and column indices
252  int8 i,
253  j;
254 
255  // general loop counter
256  int8 k;
257 
258  // timeout ctr for number of passes of the algorithm
259  int8 ctr;
260 
261  // initialize eigenvectors matrix and eigenvalues array
262  for (i = 0; i < n; i++)
263  {
264  // loop over all columns
265  for (j = 0; j < n; j++)
266  {
267  // set on diagonal and off-diagonal elements to zero
268  eigvec[i][j] = 0.0F;
269  }
270 
271  // correct the diagonal elements to 1.0
272  eigvec[i][i] = 1.0F;
273 
274  // initialize the array of eigenvalues to the diagonal elements of A
275  eigval[i] = A[i][i];
276  }
277 
278  // initialize the counter and loop until converged or NITERATIONS reached
279  ctr = 0;
280  do
281  {
282  // compute the absolute value of the above diagonal elements as exit criterion
283  residue = 0.0F;
284 
285  // loop over rows excluding last row
286  for (i = 0; i < n - 1; i++)
287  {
288  // loop over above diagonal columns
289  for (j = i + 1; j < n; j++)
290  {
291  // accumulate the residual off diagonal terms which are being driven to zero
292  residue += fabsf(A[i][j]);
293  }
294  }
295 
296  // check if we still have work to do
297  if (residue > 0.0F)
298  {
299  // loop over all rows with the exception of the last row (since only rotating above diagonal elements)
300  for (i = 0; i < n - 1; i++)
301  {
302  // loop over columns j (where j is always greater than i since above diagonal)
303  for (j = i + 1; j < n; j++)
304  {
305  // only continue with this element if the element is non-zero
306  if (fabsf(A[i][j]) > 0.0F)
307  {
308  // calculate cot(2*phi) where phi is the Jacobi rotation angle
309  cot2phi = 0.5F * (eigval[j] - eigval[i]) / (A[i][j]);
310 
311  // calculate tan(phi) correcting sign to ensure the smaller solution is used
312  tanphi = 1.0F / (fabsf(cot2phi) + sqrtf(1.0F + cot2phi * cot2phi));
313  if (cot2phi < 0.0F)
314  {
315  tanphi = -tanphi;
316  }
317 
318  // calculate the sine and cosine of the Jacobi rotation angle phi
319  cosphi = 1.0F / sqrtf(1.0F + tanphi * tanphi);
320  sinphi = tanphi * cosphi;
321 
322  // calculate tan(phi/2)
323  tanhalfphi = sinphi / (1.0F + cosphi);
324 
325  // set tmp = tan(phi) times current matrix element used in update of leading diagonal elements
326  ftmp = tanphi * A[i][j];
327 
328  // apply the jacobi rotation to diagonal elements [i][i] and [j][j] stored in the eigenvalue array
329  // eigval[i] = eigval[i] - tan(phi) * A[i][j]
330  eigval[i] -= ftmp;
331 
332  // eigval[j] = eigval[j] + tan(phi) * A[i][j]
333  eigval[j] += ftmp;
334 
335  // by definition, applying the jacobi rotation on element i, j results in 0.0
336  A[i][j] = 0.0F;
337 
338  // apply the jacobi rotation to all elements of the eigenvector matrix
339  for (k = 0; k < n; k++)
340  {
341  // store eigvec[k][i]
342  ftmp = eigvec[k][i];
343 
344  // eigvec[k][i] = eigvec[k][i] - sin(phi) * (eigvec[k][j] + tan(phi/2) * eigvec[k][i])
345  eigvec[k][i] = ftmp - sinphi * (eigvec[k][j] + tanhalfphi * ftmp);
346 
347  // eigvec[k][j] = eigvec[k][j] + sin(phi) * (eigvec[k][i] - tan(phi/2) * eigvec[k][j])
348  eigvec[k][j] = eigvec[k][j] + sinphi * (ftmp - tanhalfphi * eigvec[k][j]);
349  }
350 
351  // apply the jacobi rotation only to those elements of matrix m that can change
352  for (k = 0; k <= i - 1; k++)
353  {
354  // store A[k][i]
355  ftmp = A[k][i];
356 
357  // A[k][i] = A[k][i] - sin(phi) * (A[k][j] + tan(phi/2) * A[k][i])
358  A[k][i] = ftmp - sinphi * (A[k][j] + tanhalfphi * ftmp);
359 
360  // A[k][j] = A[k][j] + sin(phi) * (A[k][i] - tan(phi/2) * A[k][j])
361  A[k][j] = A[k][j] + sinphi * (ftmp - tanhalfphi * A[k][j]);
362  }
363 
364  for (k = i + 1; k <= j - 1; k++)
365  {
366  // store A[i][k]
367  ftmp = A[i][k];
368 
369  // A[i][k] = A[i][k] - sin(phi) * (A[k][j] + tan(phi/2) * A[i][k])
370  A[i][k] = ftmp - sinphi * (A[k][j] + tanhalfphi * ftmp);
371 
372  // A[k][j] = A[k][j] + sin(phi) * (A[i][k] - tan(phi/2) * A[k][j])
373  A[k][j] = A[k][j] + sinphi * (ftmp - tanhalfphi * A[k][j]);
374  }
375 
376  for (k = j + 1; k < n; k++)
377  {
378  // store A[i][k]
379  ftmp = A[i][k];
380 
381  // A[i][k] = A[i][k] - sin(phi) * (A[j][k] + tan(phi/2) * A[i][k])
382  A[i][k] = ftmp - sinphi * (A[j][k] + tanhalfphi * ftmp);
383 
384  // A[j][k] = A[j][k] + sin(phi) * (A[i][k] - tan(phi/2) * A[j][k])
385  A[j][k] = A[j][k] + sinphi * (ftmp - tanhalfphi * A[j][k]);
386  }
387  } // end of test for matrix element A[i][j] non-zero
388  } // end of loop over columns j
389  } // end of loop over rows i
390  } // end of test for non-zero value of residue
391  } while ((residue > 0.0F) && (ctr++ < NITERATIONS));
392 
393  // end of main loop
394  return;
395 }
#define NITERATIONS
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void fEigenCompute4 ( float  A[][4],
float  eigval[],
float  eigvec[][4],
int8  n 
)

function computes all eigenvalues and eigenvectors of a real symmetric matrix A[0..n-1][0..n-1] stored in the top left of a 4x4 array A[4][4] A[][] is changed on output. The eigenvectors are not sorted by value. This function is identical to eigencompute10 except for the workaround for 4x4 matrices since C cannot handle functions accepting matrices with variable numbers of columns.

Parameters
eigvaleigval[0..n-1] returns the eigenvalues of A[][].
eigveceigvec[0..n-1][0..n-1] returns the normalized eigenvectors of A[][]
nn can vary up to and including 4 but the matrices A and eigvec must have 4 columns.

Definition at line 407 of file matrix.c.

408 {
409  // maximum number of iterations to achieve convergence: in practice 6 is typical
410 #define NITERATIONS 15
411  // various trig functions of the jacobi rotation angle phi
412  float cot2phi,
413  tanhalfphi,
414  tanphi,
415  sinphi,
416  cosphi;
417 
418  // scratch variable to prevent over-writing during rotations
419  float ftmp;
420 
421  // residue from remaining non-zero above diagonal terms
422  float residue;
423 
424  // matrix row and column indices
425  int8 ir,
426  ic;
427 
428  // general loop counter
429  int8 j;
430 
431  // timeout ctr for number of passes of the algorithm
432  int8 ctr;
433 
434  // initialize eigenvectors matrix and eigenvalues array
435  for (ir = 0; ir < n; ir++)
436  {
437  // loop over all columns
438  for (ic = 0; ic < n; ic++)
439  {
440  // set on diagonal and off-diagonal elements to zero
441  eigvec[ir][ic] = 0.0F;
442  }
443 
444  // correct the diagonal elements to 1.0
445  eigvec[ir][ir] = 1.0F;
446 
447  // initialize the array of eigenvalues to the diagonal elements of m
448  eigval[ir] = A[ir][ir];
449  }
450 
451  // initialize the counter and loop until converged or NITERATIONS reached
452  ctr = 0;
453  do
454  {
455  // compute the absolute value of the above diagonal elements as exit criterion
456  residue = 0.0F;
457 
458  // loop over rows excluding last row
459  for (ir = 0; ir < n - 1; ir++)
460  {
461  // loop over above diagonal columns
462  for (ic = ir + 1; ic < n; ic++)
463  {
464  // accumulate the residual off diagonal terms which are being driven to zero
465  residue += fabsf(A[ir][ic]);
466  }
467  }
468 
469  // check if we still have work to do
470  if (residue > 0.0F)
471  {
472  // loop over all rows with the exception of the last row (since only rotating above diagonal elements)
473  for (ir = 0; ir < n - 1; ir++)
474  {
475  // loop over columns ic (where ic is always greater than ir since above diagonal)
476  for (ic = ir + 1; ic < n; ic++)
477  {
478  // only continue with this element if the element is non-zero
479  if (fabsf(A[ir][ic]) > 0.0F)
480  {
481  // calculate cot(2*phi) where phi is the Jacobi rotation angle
482  cot2phi = 0.5F *
483  (eigval[ic] - eigval[ir]) /
484  (A[ir][ic]);
485 
486  // calculate tan(phi) correcting sign to ensure the smaller solution is used
487  tanphi = 1.0F / (fabsf(cot2phi) + sqrtf(1.0F + cot2phi * cot2phi));
488  if (cot2phi < 0.0F)
489  {
490  tanphi = -tanphi;
491  }
492 
493  // calculate the sine and cosine of the Jacobi rotation angle phi
494  cosphi = 1.0F / sqrtf(1.0F + tanphi * tanphi);
495  sinphi = tanphi * cosphi;
496 
497  // calculate tan(phi/2)
498  tanhalfphi = sinphi / (1.0F + cosphi);
499 
500  // set tmp = tan(phi) times current matrix element used in update of leading diagonal elements
501  ftmp = tanphi * A[ir][ic];
502 
503  // apply the jacobi rotation to diagonal elements [ir][ir] and [ic][ic] stored in the eigenvalue array
504  // eigval[ir] = eigval[ir] - tan(phi) * A[ir][ic]
505  eigval[ir] -= ftmp;
506 
507  // eigval[ic] = eigval[ic] + tan(phi) * A[ir][ic]
508  eigval[ic] += ftmp;
509 
510  // by definition, applying the jacobi rotation on element ir, ic results in 0.0
511  A[ir][ic] = 0.0F;
512 
513  // apply the jacobi rotation to all elements of the eigenvector matrix
514  for (j = 0; j < n; j++)
515  {
516  // store eigvec[j][ir]
517  ftmp = eigvec[j][ir];
518 
519  // eigvec[j][ir] = eigvec[j][ir] - sin(phi) * (eigvec[j][ic] + tan(phi/2) * eigvec[j][ir])
520  eigvec[j][ir] = ftmp - sinphi * (eigvec[j][ic] + tanhalfphi * ftmp);
521 
522  // eigvec[j][ic] = eigvec[j][ic] + sin(phi) * (eigvec[j][ir] - tan(phi/2) * eigvec[j][ic])
523  eigvec[j][ic] = eigvec[j][ic] + sinphi * (ftmp - tanhalfphi * eigvec[j][ic]);
524  }
525 
526  // apply the jacobi rotation only to those elements of matrix m that can change
527  for (j = 0; j <= ir - 1; j++)
528  {
529  // store A[j][ir]
530  ftmp = A[j][ir];
531 
532  // A[j][ir] = A[j][ir] - sin(phi) * (A[j][ic] + tan(phi/2) * A[j][ir])
533  A[j][ir] = ftmp - sinphi * (A[j][ic] + tanhalfphi * ftmp);
534 
535  // A[j][ic] = A[j][ic] + sin(phi) * (A[j][ir] - tan(phi/2) * A[j][ic])
536  A[j][ic] = A[j][ic] + sinphi * (ftmp - tanhalfphi * A[j][ic]);
537  }
538 
539  for (j = ir + 1; j <= ic - 1; j++)
540  {
541  // store A[ir][j]
542  ftmp = A[ir][j];
543 
544  // A[ir][j] = A[ir][j] - sin(phi) * (A[j][ic] + tan(phi/2) * A[ir][j])
545  A[ir][j] = ftmp - sinphi * (A[j][ic] + tanhalfphi * ftmp);
546 
547  // A[j][ic] = A[j][ic] + sin(phi) * (A[ir][j] - tan(phi/2) * A[j][ic])
548  A[j][ic] = A[j][ic] + sinphi * (ftmp - tanhalfphi * A[j][ic]);
549  }
550 
551  for (j = ic + 1; j < n; j++)
552  {
553  // store A[ir][j]
554  ftmp = A[ir][j];
555 
556  // A[ir][j] = A[ir][j] - sin(phi) * (A[ic][j] + tan(phi/2) * A[ir][j])
557  A[ir][j] = ftmp - sinphi * (A[ic][j] + tanhalfphi * ftmp);
558 
559  // A[ic][j] = A[ic][j] + sin(phi) * (A[ir][j] - tan(phi/2) * A[ic][j])
560  A[ic][j] = A[ic][j] + sinphi * (ftmp - tanhalfphi * A[ic][j]);
561  }
562  } // end of test for matrix element already zero
563  } // end of loop over columns
564  } // end of loop over rows
565  } // end of test for non-zero residue
566  } while ((residue > 0.0F) && (ctr++ < NITERATIONS));
567 
568  // end of main loop
569  return;
570 }
#define NITERATIONS
int8_t int8
Definition: sensor_fusion.h:55
void fmatrixAeqI ( float *  A[],
int16  rc 
)

function sets the matrix A to the identity matrix

Parameters
Apointer to the matrix
rcdimension of the matrix

Definition at line 87 of file matrix.c.

Referenced by fmatrixAeqInvA().

88 {
89  // rc = rows and columns in A
90  float *pAij; // pointer to A[i][j]
91  int8 i,
92  j; // loop counters
93  for (i = 0; i < rc; i++)
94  {
95  // set pAij to &A[i][j=0]
96  pAij = A[i];
97  for (j = 0; j < rc; j++)
98  {
99  *(pAij++) = 0.0F;
100  }
101 
102  A[i][i] = 1.0F;
103  }
104 
105  return;
106 }
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the caller graph for this function:

void fmatrixAeqInvA ( float *  A[],
int8  iColInd[],
int8  iRowInd[],
int8  iPivot[],
int8  isize,
int8 pierror 
)

function uses Gauss-Jordan elimination to compute the inverse of matrix A in situ on exit, A is replaced with its inverse

Definition at line 666 of file matrix.c.

Referenced by fComputeAccelCalibration4(), fComputeMagCalibration4(), fRun_6DOF_GY_KALMAN(), and fUpdateMagCalibration4Slice().

668 {
669  float largest; // largest element used for pivoting
670  float scaling; // scaling factor in pivoting
671  float recippiv; // reciprocal of pivot element
672  float ftmp; // temporary variable used in swaps
673  int8 i,
674  j,
675  k,
676  l,
677  m; // index counters
678  int8 iPivotRow,
679  iPivotCol; // row and column of pivot element
680 
681  // to avoid compiler warnings
682  iPivotRow = iPivotCol = 0;
683 
684  // default to successful inversion
685  *pierror = false;
686 
687  // initialize the pivot array to 0
688  for (j = 0; j < isize; j++)
689  {
690  iPivot[j] = 0;
691  }
692 
693  // main loop i over the dimensions of the square matrix A
694  for (i = 0; i < isize; i++)
695  {
696  // zero the largest element found for pivoting
697  largest = 0.0F;
698 
699  // loop over candidate rows j
700  for (j = 0; j < isize; j++)
701  {
702  // check if row j has been previously pivoted
703  if (iPivot[j] != 1)
704  {
705  // loop over candidate columns k
706  for (k = 0; k < isize; k++)
707  {
708  // check if column k has previously been pivoted
709  if (iPivot[k] == 0)
710  {
711  // check if the pivot element is the largest found so far
712  if (fabsf(A[j][k]) >= largest)
713  {
714  // and store this location as the current best candidate for pivoting
715  iPivotRow = j;
716  iPivotCol = k;
717  largest = (float) fabsf(A[iPivotRow][iPivotCol]);
718  }
719  }
720  else if (iPivot[k] > 1)
721  {
722  // zero determinant situation: exit with identity matrix and set error flag
723  fmatrixAeqI(A, isize);
724  *pierror = true;
725  return;
726  }
727  }
728  }
729  }
730 
731  // increment the entry in iPivot to denote it has been selected for pivoting
732  iPivot[iPivotCol]++;
733 
734  // check the pivot rows iPivotRow and iPivotCol are not the same before swapping
735  if (iPivotRow != iPivotCol)
736  {
737  // loop over columns l
738  for (l = 0; l < isize; l++)
739  {
740  // and swap all elements of rows iPivotRow and iPivotCol
741  ftmp = A[iPivotRow][l];
742  A[iPivotRow][l] = A[iPivotCol][l];
743  A[iPivotCol][l] = ftmp;
744  }
745  }
746 
747  // record that on the i-th iteration rows iPivotRow and iPivotCol were swapped
748  iRowInd[i] = iPivotRow;
749  iColInd[i] = iPivotCol;
750 
751  // check for zero on-diagonal element (singular matrix) and return with identity matrix if detected
752  if (A[iPivotCol][iPivotCol] == 0.0F)
753  {
754  // zero determinant situation: exit with identity matrix and set error flag
755  fmatrixAeqI(A, isize);
756  *pierror = true;
757  return;
758  }
759 
760  // calculate the reciprocal of the pivot element knowing it's non-zero
761  recippiv = 1.0F / A[iPivotCol][iPivotCol];
762 
763  // by definition, the diagonal element normalizes to 1
764  A[iPivotCol][iPivotCol] = 1.0F;
765 
766  // multiply all of row iPivotCol by the reciprocal of the pivot element including the diagonal element
767  // the diagonal element A[iPivotCol][iPivotCol] now has value equal to the reciprocal of its previous value
768  for (l = 0; l < isize; l++)
769  {
770  if (A[iPivotCol][l] != 0.0F) A[iPivotCol][l] *= recippiv;
771  }
772 
773  // loop over all rows m of A
774  for (m = 0; m < isize; m++)
775  {
776  if (m != iPivotCol)
777  {
778  // scaling factor for this row m is in column iPivotCol
779  scaling = A[m][iPivotCol];
780 
781  // zero this element
782  A[m][iPivotCol] = 0.0F;
783 
784  // loop over all columns l of A and perform elimination
785  for (l = 0; l < isize; l++)
786  {
787  if ((A[iPivotCol][l] != 0.0F) && (scaling != 0.0F))
788  A[m][l] -= A[iPivotCol][l] * scaling;
789  }
790  }
791  }
792  } // end of loop i over the matrix dimensions
793 
794  // finally, loop in inverse order to apply the missing column swaps
795  for (l = isize - 1; l >= 0; l--)
796  {
797  // set i and j to the two columns to be swapped
798  i = iRowInd[l];
799  j = iColInd[l];
800 
801  // check that the two columns i and j to be swapped are not the same
802  if (i != j)
803  {
804  // loop over all rows k to swap columns i and j of A
805  for (k = 0; k < isize; k++)
806  {
807  ftmp = A[k][i];
808  A[k][i] = A[k][j];
809  A[k][j] = ftmp;
810  }
811  }
812  }
813 
814  return;
815 }
void fmatrixAeqI(float *A[], int16 rc)
function sets the matrix A to the identity matrix
Definition: matrix.c:87
int8_t int8
Definition: sensor_fusion.h:55

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void fVeq3x3AxV ( float  V[3],
float  A[][3] 
)

function multiplies the 3x1 vector V by a 3x3 matrix A

Parameters
Vused for both input and output

Definition at line 871 of file matrix.c.

Referenced by fRunAccelCalibration().

872 {
873  float ftmp[3]; // scratch vector
874 
875  // set ftmp = V
876  ftmp[CHX] = V[CHX];
877  ftmp[CHY] = V[CHY];
878  ftmp[CHZ] = V[CHZ];
879 
880  // set V = A * ftmp = A * V
881  V[CHX] = A[CHX][CHX] *
882  ftmp[CHX] +
883  A[CHX][CHY] *
884  ftmp[CHY] +
885  A[CHX][CHZ] *
886  ftmp[CHZ];
887  V[CHY] = A[CHY][CHX] *
888  ftmp[CHX] +
889  A[CHY][CHY] *
890  ftmp[CHY] +
891  A[CHY][CHZ] *
892  ftmp[CHZ];
893  V[CHZ] = A[CHZ][CHX] *
894  ftmp[CHX] +
895  A[CHZ][CHY] *
896  ftmp[CHY] +
897  A[CHZ][CHZ] *
898  ftmp[CHZ];
899 
900  return;
901 }
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
#define CHZ
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76

+ Here is the caller graph for this function:

void fveqRu ( float  fv[],
float  fR[][3],
float  fu[],
int8  itranspose 
)

function rotates 3x1 vector u onto 3x1 vector using 3x3 rotation matrix fR. the rotation is applied in the inverse direction if itranpose is true

Parameters
fv3x1 output vector
fRrotation matrix
fu3x1 input vector
itransposetrue if inverse direction desired

Definition at line 820 of file matrix.c.

Referenced by fRun_6DOF_GY_KALMAN().

821 {
822  if (!itranspose)
823  {
824  // normal, non-transposed rotation
825  fv[CHX] = fR[CHX][CHX] *
826  fu[CHX] +
827  fR[CHX][CHY] *
828  fu[CHY] +
829  fR[CHX][CHZ] *
830  fu[CHZ];
831  fv[CHY] = fR[CHY][CHX] *
832  fu[CHX] +
833  fR[CHY][CHY] *
834  fu[CHY] +
835  fR[CHY][CHZ] *
836  fu[CHZ];
837  fv[CHZ] = fR[CHZ][CHX] *
838  fu[CHX] +
839  fR[CHZ][CHY] *
840  fu[CHY] +
841  fR[CHZ][CHZ] *
842  fu[CHZ];
843  }
844  else
845  {
846  // transposed (inverse rotation)
847  fv[CHX] = fR[CHX][CHX] *
848  fu[CHX] +
849  fR[CHY][CHX] *
850  fu[CHY] +
851  fR[CHZ][CHX] *
852  fu[CHZ];
853  fv[CHY] = fR[CHX][CHY] *
854  fu[CHX] +
855  fR[CHY][CHY] *
856  fu[CHY] +
857  fR[CHZ][CHY] *
858  fu[CHZ];
859  fv[CHZ] = fR[CHX][CHZ] *
860  fu[CHX] +
861  fR[CHY][CHZ] *
862  fu[CHY] +
863  fR[CHZ][CHZ] *
864  fu[CHZ];
865  }
866 
867  return;
868 }
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
#define CHZ
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76

+ Here is the caller graph for this function: